package coursework.receivers;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.Socket;
import java.util.*;

import javax.swing.JFrame;

public class Receiver extends JFrame{

	private Hashtable<Integer, String> messages = new Hashtable<Integer, String>();
	private Hashtable<Integer, String> retransmitCodes = new Hashtable<Integer, String>();
	private PriorityQueue<Sample> samples = new PriorityQueue<Sample>();
	private int delay;
	private int period;
	private static int id = 0;
	private Vector<String> userMessages = new Vector<String>();
	
	public Receiver(){
		super("Receiver " + id);
		id++;
		setSize(200, 100);
		setVisible(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		// TODO Auto-generated constructor stub
		try {
			init();
			Socket client = new Socket("localhost",7777);
			BufferedReader userIn = new BufferedReader(new InputStreamReader(System.in));
			BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
			DataOutputStream out = new DataOutputStream(client.getOutputStream());

			//Start UserInputThread so it can run in the background gathering user input
			UserInputThread userThread = new UserInputThread(this,userIn);
			userThread.start();
			
			
			//Greet/Connect part of protocol
			String serverMessage = in.readLine();
			out.writeBytes(messages.get(102));
			serverMessage = in.readLine();
			if(!serverMessage.equals(messages.get(103))) throw new ReceiverException("Handshaking protocol not completed, possible connection/server error, please restart receiver to retry");
			
			//Transmission Delay test
			serverMessage = in.readLine();
			while(serverMessage.equals(messages.get(104))){
				out.writeBytes(messages.get(104));
				serverMessage = in.readLine();
			}
			System.out.println("Connection established and transmission test successfully completed." +
					"Please enter 'START' to start transmission.");
			
			//Wait for user to start
			String userMessage = getUserMessage();
			while(!userMessage.equals("START")){
				System.out.println("Please enter 'START' to start transmission.");
				userMessage = getUserMessage();
			}
			
			//Start trasnmission
			out.writeBytes(messages.get(201));
			serverMessage = in.readLine();
			while(!serverMessage.substring(0, 3).equals("201")){
				out.writeBytes(messages.get(201));
				serverMessage = in.readLine();
			}
			
			//Get the delay and period for the timer task
			parse(serverMessage);
			Timer timer = new Timer();
			ClientTask clientTask = new ClientTask(this);
			timer.schedule(clientTask, delay, period);
			boolean receiving = true;
			while(receiving){
				serverMessage = in.readLine();
				if(serverMessage.substring(0, 3).equals("302")){
					bleepSample(parseBleep(serverMessage));
					continue;
				}
				
			}
			/*int delay;
			while(true){
				String inMessage = in.readLine();
				System.out.println("From server>" + inMessage);
				String input = userIn.readLine();
				int i = Integer.parseInt(input);
				System.out.println("Integer entered>" + i);
				if(i==666){
					break;
				}
				if(inMessage.equals(messages.get(202))){
					String delayString = inMessage.substring(inMessage.indexOf("=")+1);
					int d = Integer.parseInt(delayString);
					delay = d;
				}
				String messageOut = messages.get(i);
				System.out.println("being sent to server>" + messageOut);
				out.writeBytes(messageOut + "\n");
				Thread.sleep(10);
			}
			while(true){
				String inMessage = in.readLine();
				System.out.println("Receiver " + id + ">"+ inMessage);
				Thread.yield();
			}*/
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public Receiver(String s){
		//Test constructor
	}
	
	public int parseBleep(String bleepMessage){
		int a = bleepMessage.indexOf("#");
		return Integer.parseInt(bleepMessage.substring(a+1));
	}
	public void parse(String string){
		//Parses string of the form "202 TRANSMIT ACCEPT DELAY=1000;PERIOD=50;"
		int a = string.indexOf("=");
		int b = string.indexOf(";");
		String delayString = string.substring(a+1, b);
		delay = Integer.parseInt(delayString);
		int c = string.substring(b+1).indexOf("=");
		int d = string.substring(b+1).indexOf(";");
		String periodString = string.substring((b+1)+c+1, (b+1)+d);
		period = Integer.parseInt(periodString);
	}
	
	public static Sample parseSample(String sample){
		//Parses strings of the form "301 SAMPLE #89#ONE ONE ONE"
		int a = sample.indexOf("#");
		int b = sample.substring(a+1).indexOf("#");
		String sampleNoString = sample.substring(a+1,(a+1)+b);
		int sampleNo = Integer.parseInt(sampleNoString);
		String sampleString = sample.substring((a+1)+b+1);
		return new Sample(sampleNo, sampleString);
	}
	
	public static Sample parseRetransmitSample(String sample){
		//Parses strings of the form "301 SAMPLE #89#ONE ONE ONE"
		int a = sample.indexOf("#");
		int b = sample.substring(a+1).indexOf("#");
		String sampleNoString = sample.substring(a+1,(a+1)+b);
		int sampleNo = Integer.parseInt(sampleNoString);
		String sampleString = sample.substring((a+1)+b+1);
		return new Sample(sampleNo, sampleString);
	}
	
	private void init(){
		//Connection
		messages.put(101, "101 CONNECT?");
		messages.put(102, "102 CONNECT ACCEPT");
		messages.put(103, "103 CONNECTED");
		messages.put(104, "104 DELAY TEST");
		messages.put(105, "105 DELAY TEST COMPLETE");
		//Start Transmit
		messages.put(201, "201 START TRANSMIT");
		messages.put(202, "202 TRANSMIT ACCEPT DELAY=");
		//Transmissio
		messages.put(301, "301 SAMPLE #");
		messages.put(302, "302 BLEEP #");
		messages.put(303, "303 RETRANSMIT #");
		messages.put(304, "304 RETRANSMIT #");
		//Stop transmit
		messages.put(401, "401 STOP TRANSMIT");
		messages.put(402, "402 STOP TRANSMIT ACCEPT");
		//Disconnect
		messages.put(501, "501 DISCONNECT");
		messages.put(502, "502 DISCONNECT ACCEPT");

		messages.put(601, "601 UNKNOWN REQUEST");
		
		retransmitCodes.put(1, "One");
		retransmitCodes.put(2, "Two Two");
		retransmitCodes.put(3, "Three Three Three");
		retransmitCodes.put(4, "Four Four Four Four");
		retransmitCodes.put(5, "Five Five Five Five Five");
		retransmitCodes.put(6, "Six Six Six Six Six Six");
		retransmitCodes.put(7, "Seven Seven Seven Seven Seven Seven Seven");
		retransmitCodes.put(8, "Eight Eight Eight Eight Eight Eight Eight Eight");
		retransmitCodes.put(9, "Nine Nine Nine Nine Nine Nine Nine Nine Nine");
		retransmitCodes.put(10, "Ten Ten Ten Ten Ten Ten Ten Ten Ten Ten");
		
	}
	
	public synchronized void addSample(Sample sample){
		samples.add(sample);
	}
	
	public synchronized Sample removeSample(){
		return samples.poll();
	}
	
	public synchronized void bleepSample(int sampleNo){
		Sample sample = new Sample(sampleNo,"BLEEP!");
		samples.remove(sample);
		samples.add(sample);
	}
	
	public synchronized void addUserMessage(String message){
		userMessages.add(message);
	}
	
	public synchronized String getUserMessage(){
		if(userMessages.size()==0)return null;
		return userMessages.remove(0);
	}
	
	public int getDelay() {
		return delay;
	}

	public int getPeriod() {
		return period;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Receiver receiver = new Receiver("Test");
		receiver.parse("202 TRANSMIT ACCEPT DELAY=1000;PERIOD=50;");
		System.out.println("Period" + receiver.getPeriod());
		System.out.println("DELAY" + receiver.getDelay());
		Sample s = receiver.parseSample("301 SAMPLE #89#ONE ONE ONE");
		System.out.println(s);
	}


}
